package com.ming.controller;

import com.ming.config.properties.FileUploadProperties;
import com.ming.exception.FileException;
import com.ming.pojo.vo.Result;
import com.ming.pojo.vo.FileUploadVO;
import com.ming.service.FileService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import jakarta.servlet.http.HttpServletRequest;

/**
 * 统一的文件控制器 - 处理文件上传、访问、下载、删除
 */
@Slf4j
@RestController
@RequestMapping("/files")
@RequiredArgsConstructor
public class FileController {

    private final FileService fileService;
    private final FileUploadProperties fileUploadProperties;

    /**
     * 文件上传
     */
    @PostMapping("/upload")
    public Result uploadFile(@RequestParam("file") MultipartFile file) throws IOException {
        log.info("开始上传文件: {}", file.getOriginalFilename());
        FileUploadVO uploadResult = fileService.uploadFile(file);
        log.info("文件上传成功: {}", uploadResult.getFileName());
        return Result.success(uploadResult);
    }

    /**
     * 文件访问（支持预览）- 仅本地存储时生效
     */
    @GetMapping("/access/**")
    @ConditionalOnProperty(name = "file.type", havingValue = "local", matchIfMissing = true)
    public ResponseEntity<Resource> getFile(HttpServletRequest request) {
        String requestURI = request.getRequestURI();
        // 提取 /files/access/ 后面的路径部分
        String filename = requestURI.substring("/files/access/".length());
        log.info("请求访问文件: {}", filename);

        try {
            String uploadPath = fileUploadProperties.getLocal().getUploadPath();
            Path filePath = Paths.get(uploadPath, filename);

            if (!Files.exists(filePath) || !Files.isReadable(filePath)) {
                log.warn("文件不存在或不可读: {}", filePath);
                throw FileException.notFound("文件不存在或不可读: " + filename);
            }

            Resource resource = new FileSystemResource(filePath.toFile());
            String contentType = Files.probeContentType(filePath);
            if (contentType == null) {
                contentType = "application/octet-stream";
            }

            HttpHeaders headers = new HttpHeaders();
            headers.add(HttpHeaders.CONTENT_TYPE, contentType);
            headers.add(HttpHeaders.CONTENT_DISPOSITION, "inline; filename=\"" + filePath.getFileName().toString() + "\"");

            // 图片文件缓存1天
            if (contentType.startsWith("image/")) {
                headers.add(HttpHeaders.CACHE_CONTROL, "public, max-age=86400");
            }

            return ResponseEntity.ok()
                    .headers(headers)
                    .contentLength(resource.contentLength())
                    .body(resource);

        } catch (Exception e) {
            log.error("访问文件失败: {}", e.getMessage(), e);
            throw FileException.of("文件访问失败：" + e.getMessage(), e);
        }
    }

    /**
     * 文件下载 - 仅本地存储时生效
     */
    @GetMapping("/download/**")
    @ConditionalOnProperty(name = "file.type", havingValue = "local", matchIfMissing = true)
    public ResponseEntity<Resource> downloadFile(HttpServletRequest request) {
        String requestURI = request.getRequestURI();
        // 提取 /files/download/ 后面的路径部分
        String filename = requestURI.substring("/files/download/".length());
        log.info("请求下载文件: {}", filename);

        try {
            String uploadPath = fileUploadProperties.getLocal().getUploadPath();
            Path filePath = Paths.get(uploadPath, filename);

            if (!Files.exists(filePath) || !Files.isReadable(filePath)) {
                log.warn("下载文件不存在或不可读: {}", filePath);
                throw FileException.notFound("下载文件不存在或不可读: " + filename);
            }

            Resource resource = new FileSystemResource(filePath.toFile());
            String contentType = Files.probeContentType(filePath);
            if (contentType == null) {
                contentType = "application/octet-stream";
            }

            HttpHeaders headers = new HttpHeaders();
            headers.add(HttpHeaders.CONTENT_TYPE, contentType);
            headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + filePath.getFileName().toString() + "\"");

            return ResponseEntity.ok()
                    .headers(headers)
                    .contentLength(resource.contentLength())
                    .body(resource);

        } catch (Exception e) {
            log.error("文件下载失败: {}", e.getMessage(), e);
            throw FileException.downloadFailed("文件下载失败：" + e.getMessage(), e);
        }
    }

    /**
     * 删除文件
     */
    @DeleteMapping("/{filename:.+}")
    public Result deleteFile(@PathVariable String filename) throws IOException {
        log.info("开始删除文件: {}", filename);
        fileService.deleteFile(filename);
        log.info("文件删除成功: {}", filename);
        return Result.success();
    }
}